// 合法的:  212 215u 0xFeeL
// 非法的：8 不是八进制的数字:078
// 非法的：不能重复后缀:032UU

/*
85         十进制
0213       八进制
0x4b      十六进制
30         整数
30u        无符号整数
30l        长整数
30ul       无符号长整数
*/

// 3.14159       // 合法的
// 314159E-5L    // 合法的
// 510E          // 非法的：不完整的指数
// 210f          // 非法的：没有小数或指数
// .e55          // 非法的：缺少整数或分数

// 在 C++中，有两种简单的定义常量的方式：
//
// #define 预处理器 ：#define 【常量名】 【值】
// 使用 const 关键字:const [类型] [常量名] = 【常量值】
// #define 预处理器
// 下面是使用
// #define 预处理器定义常量的形式：

//区别：
// 1. 作用域
// const：const 关键字定义的常量具有块作用域、函数作用域或全局作用域，具体取决于其声明的位置。如果 const 是在函数内部声明的，
// 那么它的作用域就限制在该函数内部；如果它是在文件级别声明的，那么它的作用域就是全局的，但只限于该文件（除非使用了 extern 关键字）。
// define：#define 指令是预处理器指令，它在预处理阶段将标识符替换为文本。因此，#define 定义的宏没有作用域的概念，
// 它在被定义的点之后到文件结束（或 #undef 指令）之前都是可见的。这可能导致命名冲突和难以追踪的错误。
// 2. 类型检查
// const：const 常量具有类型，因此编译器可以进行类型检查。如果尝试将 const 常量赋值给不兼容类型的变量，编译器将报错。
// define：#define 宏不进行类型检查。它们只是简单的文本替换，因此如果宏展开后的表达式与上下文类型不匹配，可能会导致编译错误或运行时错误，且这些错误可能更难以诊断。
// 3. 存储方式和内存分配
// const：const 常量在内存中通常具有存储位置（除非它们被优化掉），并且其值在编译时或程序运行时被确定。它们的存储方式和普通变量类似，但一旦被初始化后就不能被修改。
// define：#define 宏在预处理阶段被替换，因此它们不占用内存空间。它们只是简单的文本替换，不涉及内存分配。
// 4. 调试
// const：由于 const 常量具有类型并占用内存，因此它们可以被调试器识别并检查。
// define：#define 宏在预处理后就不存在了，因此调试时无法直接看到它们的值或跟踪它们的使用。
// 结论
// 尽管 const 和 #define 都可以用来定义常量，但 const 提供了更多的类型安全性和作用域控制，是现代 C 和 C++ 编程中更推荐的方式。
// #define宏通常用于条件编译、宏函数（内联代码片段）等场景，但在定义常量时应尽量避免使用，以减少出错的可能性。

/*
const	const 定义常量，表示该变量的值不能被修改。
volatile	修饰符 volatile 告诉该变量的值可能会被程序以外的因素改变，如硬件或其他线程。。
restrict	由 restrict 修饰的指针是唯一一种访问它所指向的对象的方式。只有 C99 增加了新的类型限定符 restrict。
mutable	表示类中的成员变量可以在 const 成员函数中被修改。
static	用于定义静态变量，表示该变量的作用域仅限于当前文件或当前函数内，不会被其他文件或函数访问。
register	用于定义寄存器变量，表示该变量被频繁使用，可以存储在CPU的寄存器中，以提高程序的运行效率。*/

#include <iostream>
using namespace std;

#define LENGTH 10
const int WIDTH = 5;

int sun() {
    int area = LENGTH * WIDTH;
    cout <<area;
    return 0;
}
